package com.vca.service.service.Impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.vca.common.constants.Constants;
import com.vca.common.constants.OrderRedisConstans;
import com.vca.common.exception.VcaException;
import com.vca.common.model.exceptions.ThirdPartyExceptions;
import com.vca.common.model.order.StoreOrder;
import com.vca.common.model.order.StoreOrderInfo;
import com.vca.common.model.sf.*;
import com.vca.common.model.sms.SmsTemplate;
import com.vca.common.model.system.SystemNotification;
import com.vca.common.model.user.User;
import com.vca.common.model.user.UserToken;
import com.vca.common.request.Body;
import com.vca.common.request.StoreOrderSendRequest;
import com.vca.common.request.WaybillRoute;
import com.vca.common.response.sf.ResponseCancel;
import com.vca.common.response.sf.RoutePushResponse;
import com.vca.service.dao.order.StoreOrderDao;
import com.vca.service.dao.order.StoreOrderInfoDao;
import com.vca.service.dao.system.SystemConfigDao;
import com.vca.service.service.*;
import com.vca.service.util.SFUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;
import java.util.*;


/**
 * 顺丰
 *
 * @author wangsong
 * @version 1.0.0
 * @mail 1720696548@qq.com
 * @date 2020/9/15 0015 17:24
 */
@Service
public class SFServiceImpl implements SFService {

    @Value("${vca.proxy.disable}")
    private Boolean disable;

    @Autowired
    private SFUtil sfUtil;

    @Resource
    private StoreOrderDao storeOrderDao;

    @Resource
    private StoreOrderInfoDao storeOrderInfoDao;

    @Resource
    private SystemConfigDao systemConfigDao;

    @Autowired
    private StoreOrderStatusService storeOrderStatusService;

    @Autowired
    private TransactionTemplate transactionTemplate;

    @Autowired
    private StoreOrderServiceImpl storeOrderService;

    @Autowired
    private StoreOrderInfoService storeOrderInfoService;

    @Autowired
    private SystemConfigService systemConfigService;

    @Autowired
    private SystemNotificationService systemNotificationService;

    @Autowired
    private SmsTemplateService smsTemplateService;

    @Autowired
    private TemplateMessageService templateMessageService;

    @Autowired
    private UserService userService;

    @Autowired
    private UserTokenService userTokenService;

    @Autowired
    private SmsService smsService;

    @Autowired
    private ThirdPartyExceptionsService thirdPartyExceptionsService;

    private final Logger logger = LoggerFactory.getLogger(SFServiceImpl.class);


    /**
     * 顺丰下单 /返回单号
     *
     * @author wangsong
     * @mail 1720696548@qq.com
     * @date 2020/9/15 0015 19:36
     * @version 1.0.0
     */
    @Override
    public ResponseCancel sendSF(StoreOrderSendRequest request) {

        //查询订单信息
        LambdaQueryWrapper<StoreOrder> storeOrderLambdaQueryWrapper = new LambdaQueryWrapper<>();
        storeOrderLambdaQueryWrapper.eq(StoreOrder::getOrderId, request.getOrderNo());
        StoreOrder storeOrder = storeOrderDao.selectOne(storeOrderLambdaQueryWrapper);

        if (ObjectUtil.isNull(storeOrder)) {
            throw new VcaException("订单不存在!");
        }
        //订单校验
        if (storeOrder.getIsDel()) throw new VcaException("订单已删除,不能发货!");
        if (storeOrder.getStatus() > 0) throw new VcaException("订单已发货请勿重复操作!");
        //查询获取订单详情信息
        LambdaQueryWrapper<StoreOrderInfo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(StoreOrderInfo::getOrderNo, request.getOrderNo());
        StoreOrderInfo storeOrderInfo = storeOrderInfoDao.selectOne(lambdaQueryWrapper);
        if (ObjectUtil.isNull(storeOrderInfo)) {
            throw new VcaException("未找到该订单详情!");
        }
        //顺丰下单参数实体
        MsgData md = new MsgData();
        //托寄物信息
        List<CargoDetail> cargoDetailList = new ArrayList<>();
        CargoDetail cargoDetail = new CargoDetail();
        cargoDetail.setName(storeOrderInfo.getName());
        cargoDetail.setCount(storeOrderInfo.getPayNum());
        cargoDetail.setCargoId(storeOrderInfo.getProductId().toString());
        cargoDetailList.add(cargoDetail);
        //收寄方信息
        ArrayList<ContactInfo> contactInfos = new ArrayList<>();
        //收件人信息
        ContactInfo addresseeInfo = new ContactInfo();
        //寄件人信息
        ContactInfo senderInfo = new ContactInfo();

        addresseeInfo.setContactType(2);
        addresseeInfo.setContact(storeOrder.getRealName());
        addresseeInfo.setMobile(storeOrder.getUserPhone());
        addresseeInfo.setTel(storeOrder.getUserPhone());
        addresseeInfo.setCountry("CN");
        addresseeInfo.setAddress(storeOrder.getUserAddress());
        contactInfos.add(addresseeInfo);

        //寄件方信息

        senderInfo.setContactType(1);
        senderInfo.setContact(request.getToName());
        senderInfo.setMobile(request.getToTel());
        senderInfo.setTel(request.getToTel());
        senderInfo.setCountry("CN");
        senderInfo.setAddress(request.getToAddr());
        contactInfos.add(senderInfo);

        md.setLanguage("zh-CN");
        md.setOrderId(request.getOrderNo()); // 订单Id
        md.setCargoDetails(cargoDetailList);
        md.setContactInfoList(contactInfos);
        md.setMonthlyCard("7551234567");
        md.setExpressTypeId(1);
        md.setParcelQty(1);
        md.setVolume(storeOrderInfo.getVolume());
        md.setTotalWeight(storeOrderInfo.getWeight());
        md.setIsReturnRoutelabel(1);
        //调用第三方 返回数据
        ResponseCancel responseCreate = sfUtil.fopReceLtlCreateOrder(md, disable);
        //判断第三方是否成功  成功则拿到运单号 失败返回
        if (responseCreate.getSuccess()) {
            JSONObject msgData = responseCreate.getMsgData();
            Map<String, Object> innerMap = msgData.getInnerMap();
            JSONArray jsonArray = (JSONArray) innerMap.get("waybillNoInfoList");
            List<WaybillNoInfo> statusList = JSONObject.parseArray(jsonArray.toJSONString(), WaybillNoInfo.class);
            String waybillNo = "";
            for (int i = 0; i < statusList.size(); i++) {
                if (statusList.get(i).getWaybillType().equals(1)) {
                    waybillNo = statusList.get(i).getWaybillNo();
                }
            }

            //更新数据
            storeOrder.setDeliveryCode("SF");
            storeOrder.setDeliveryName("顺丰快递");
            storeOrder.setMasterWaybillNo(waybillNo);
            storeOrder.setStatus(1);
            storeOrder.setDeliveryType("特快");

            String message = Constants.ORDER_LOG_MESSAGE_EXPRESS.replace("{deliveryName}", "顺丰快递").replace("{deliveryCode}", storeOrder.getMasterWaybillNo());

            Boolean execute = transactionTemplate.execute(i -> {
                storeOrderDao.updateById(storeOrder);
                //订单记录增加
                storeOrderStatusService.createLog(storeOrder.getId(), Constants.ORDER_LOG_EXPRESS, 0, message);
                return Boolean.TRUE;
            });

            if (!execute) throw new VcaException("已发货,更新订单状态失败！");
        }
        return responseCreate;
    }


    /**
     * 顺丰取消订单
     *
     * @author wangsong
     * @mail 1720696548@qq.com
     * @date 2020/9/15 0015 19:36
     * @version 1.0.0
     */
    @Override
    public ResponseCancel cancelSF(String orderId) {
        //订单校验
        LambdaQueryWrapper<StoreOrder> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(StoreOrder::getOrderId, orderId);
        StoreOrder storeOrder = storeOrderDao.selectOne(lambdaQueryWrapper);
        if (ObjectUtil.isNull(storeOrder)) {
            throw new VcaException("该订单不存在！");
        }
        if (storeOrder.getIsDel()) throw new VcaException("订单已删除");
        if (storeOrder.getStatus() != 1) throw new VcaException("该订单未发货或已收货");
        //取消订单参数
        MsgDataUpdate msgDataUpdate = new MsgDataUpdate();
        msgDataUpdate.setDealType(2);
        msgDataUpdate.setLanguage("zh-CN");
        msgDataUpdate.setOrderId(orderId);
        ResponseCancel responseCancel = sfUtil.fopReceLtlCancelOrder(msgDataUpdate, disable);
        if (responseCancel.getSuccess()) {
            storeOrder.setIsDel(true);
            Boolean execute = transactionTemplate.execute(i -> {
                storeOrderDao.updateById(storeOrder);
                return Boolean.TRUE;
            });
            if (!execute) throw new VcaException("发货订单已取消,更新订单状态失败！");
        }

        return responseCancel;
    }


    /**
     * 顺丰查询下单结果
     *
     * @author wangsong
     * @mail 1720696548@qq.com
     * @date 2020/9/15 0015 19:36
     * @version 1.0.0
     */
    @Override
    public ResponseCancel getOrderResult(String orderId) {
        LambdaQueryWrapper<StoreOrder> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(StoreOrder::getOrderId, orderId);
        StoreOrder storeOrder = storeOrderDao.selectOne(lambdaQueryWrapper);
        if (ObjectUtil.isNull(storeOrder)) {
            throw new VcaException("该订单不存在！");
        }
        if (storeOrder.getIsDel()) throw new VcaException("订单已删除");
        return sfUtil.fopReceLtlGetOrderResult(orderId, disable);
    }

    /**
     * 顺丰发货订单路由
     *
     * @param orderNo
     * @return
     */
    @Override
    public ResponseCancel getOrderRouting(String language,String orderNo, Integer type) {
        LambdaQueryWrapper<StoreOrder> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(StoreOrder::getOrderId, orderNo);
        StoreOrder storeOrder = storeOrderDao.selectOne(lambdaQueryWrapper);
        if (ObjectUtil.isNull(storeOrder)) {
            if("en".equals(language)){
                throw new VcaException("This order does not exist!");
            }else{
                throw new VcaException("该订单不存在！");
            }
        }
//        if (!Objects.equals(storeOrder.getUid(),userService.getUserId())){
//            throw new VcaException("该订单不存在！");
//        }
        if (storeOrder.getIsDel()) {
            if("en".equals(language)){
                throw new VcaException("Order deleted");
            }else{
                throw new VcaException("订单已删除");
            }
        }

        ResponseCancel responseCancel = new ResponseCancel();
        //查看订单物流
        if (storeOrder.getStatus() > 0) {
            if (type.equals(1)) {
                responseCancel = sfUtil.fopReceLtlGetOrderRouting(storeOrder.getMasterWaybillNo(), disable);
            } else if (type.equals(2)) {
                responseCancel = sfUtil.fopReceLtlGetOrderRouting(storeOrder.getReturnWaybillNo(), disable);
            }

            return responseCancel;
//            Map<String, Object> innerMap = responseCancel.getMsgData().getInnerMap();
//            JSONArray jsonArray = (JSONArray) innerMap.get("routeResps");
//            JSONObject jsonObject = (JSONObject) jsonArray.get(0);
//            Object routes = jsonObject.get("routes");
//            //如果路由信息为空则为未揽件 调用取消订单接口 否则调用拦截接口
//            if (ObjectUtil.isNull(routes)) {
//                ResponseCancel cancel = storeOrderService.cancel(orderId);
//                cancel.getMsgData();//TODO 查看结果  修改状态
//            } else {
//                ResponseCancel intercept = storeOrderService.intercept(orderId);
//                intercept.getMsgData();
//            }
//            return responseCancel;
//        }
//        return null;
        }
        return responseCancel;
    }

    /**
     * @Description: 路由推送
     * @Author: xyg
     * @Date: 2022/11/21
     */
    public RoutePushResponse getRoutePush(Body Body) {
        logger.info("路由推送回调数据：" + Body.toString());
        RoutePushResponse routePushResponse = new RoutePushResponse();
        //判断顺丰订单是否为已签收状态 并变更已收货状态
        List<WaybillRoute> waybillRoutes = Body.getBody().getWaybillRoute();


        waybillRoutes.forEach(e -> {
            if (StringUtils.isNotEmpty(e.getReasonName()) || StringUtils.isNotEmpty(e.getReasonCode())) {
                ThirdPartyExceptions thirdPartyExceptions = new ThirdPartyExceptions();
                thirdPartyExceptions.setErrcode(e.getReasonCode());
                thirdPartyExceptions.setErrmsg(e.getReasonName());
                thirdPartyExceptions.setRemark("顺丰回调异常！");
                thirdPartyExceptions.setType(1);
                thirdPartyExceptions.setData(JSON.toJSON(Body).toString());
                thirdPartyExceptionsService.save(thirdPartyExceptions);
                routePushResponse.setReasonCode(e.getReasonCode());
                routePushResponse.setReturnMsg(e.getReasonName());
            } else {
                //退货订单
                StoreOrder storeOrderServiceOne = storeOrderService.getOne(new LambdaQueryWrapper<StoreOrder>().eq(StoreOrder::getReturnWaybillNo, e.getMailno()).eq(StoreOrder::getRefundStatus, 4));
                //如果退货订单不为空则为退货订单
                if (ObjectUtil.isNotEmpty(storeOrderServiceOne) && storeOrderServiceOne.getRefundStatus().equals(4)) {

                    List<StoreOrderInfo> storeOrderInfoList = storeOrderInfoService.list(new LambdaQueryWrapper<StoreOrderInfo>().eq(StoreOrderInfo::getOrderNo, storeOrderServiceOne.getOrderId()).eq(StoreOrderInfo::getRefundStatus, 4));

                    storeOrderServiceOne.setRefundStatus(5);
                    ArrayList<StoreOrderInfo> storeOrderInfos = new ArrayList<>();

                    //更新订单详情状态
                    for (StoreOrderInfo storeOrderInfo : storeOrderInfoList) {
                        storeOrderInfo.setRefundStatus(5);
                        storeOrderInfos.add(storeOrderInfo);
                    }
                    Boolean execute = transactionTemplate.execute(temp -> {
                        storeOrderService.updateById(storeOrderServiceOne);
                        storeOrderInfoService.updateBatchById(storeOrderInfos);
                        storeOrderStatusService.createLog(storeOrderServiceOne.getId(), "refundSend", 1, "退货订单已揽收");
                        return Boolean.TRUE;
                    });
                    if (!execute) {
                        throw new VcaException("订单状态更新失败");
                    }
                } else { //正常发货订单
                    if (e.getOpCode().equals("80")) {
                        LambdaQueryWrapper<StoreOrder> storeOrderLambdaQueryWrapper = new LambdaQueryWrapper<>();
                        storeOrderLambdaQueryWrapper.eq(StoreOrder::getMasterWaybillNo, e.getMailno());
                        storeOrderLambdaQueryWrapper.eq(StoreOrder::getIsDel, false);

                        StoreOrder storeOrder = storeOrderService.getOne(storeOrderLambdaQueryWrapper);


                        if (ObjectUtil.isNotEmpty(storeOrder) && storeOrder.getStatus().equals(1)) {

                            String afterSalesTime = systemConfigService.getValueByKey(Constants.AFTER_SALES_TIME);
                            Calendar calendar = Calendar.getInstance();
                            calendar.setTime(new Date());
                            calendar.set(Calendar.HOUR_OF_DAY, 0);
                            calendar.set(Calendar.MINUTE, 0);
                            calendar.set(Calendar.SECOND, 0);
                            calendar.set(Calendar.MILLISECOND, 0);
                            Date calendarTime = calendar.getTime();
                            Date addDays = DateUtils.addDays(calendarTime, Integer.parseInt(afterSalesTime) + 1);
                            storeOrder.setStatus(3);
                            storeOrder.setClosingTime(new Date());
                            storeOrder.setAfterSalesDeadline(addDays);
                            //订单详情
                            List<StoreOrderInfo> storeOrderInfoList = storeOrderInfoService.getListByOrderNo(storeOrder.getOrderId());

                            ArrayList<StoreOrderInfo> storeOrderInfos = new ArrayList<>();

                            for (StoreOrderInfo storeOrderInfo : storeOrderInfoList) {
                                storeOrderInfo.setStatus(3);
                                storeOrderInfos.add(storeOrderInfo);
                            }
                            Boolean execute = transactionTemplate.execute(temp -> {
                                storeOrderService.updateById(storeOrder);
                                storeOrderInfoService.updateBatchById(storeOrderInfos);
                                storeOrderStatusService.createLog(storeOrder.getId(), Constants.ORDER_LOG_SHOUHUO, 0, "订单已收货");
                                return Boolean.TRUE;
                            });

                            if (!execute) {
                                throw new VcaException("订单自动收货失败");
                            } else {
                                orderTakePushMessage(storeOrder); //消息通知
                            }
                        }
                    }
                }
                routePushResponse.setReasonCode(e.getReasonCode());
                routePushResponse.setReturnMsg(e.getReasonName());
            }
        });

        return routePushResponse;
    }

    /**
     * 订单收货消息通知
     *
     * @param storeOrder
     * @return
     */
    public Boolean orderTakePushMessage(StoreOrder storeOrder) {
        List<StoreOrderInfo> orderInfoList = storeOrderInfoService.list(new LambdaQueryWrapper<StoreOrderInfo>().eq(StoreOrderInfo::getOrderNo, storeOrder.getOrderId()));
        SystemNotification paySuccessOfEvent = systemNotificationService.getByMark(OrderRedisConstans.CONFIRM_RECEIPT);
        if (paySuccessOfEvent.getIsRoutine().equals(1)) {
            //  生成小程序订阅消息
            orderTakePushMessageRoutine(storeOrder, paySuccessOfEvent.getRoutineId());
        }
        if (paySuccessOfEvent.getIsWechat().equals(1)) {
            // TODO: 2023/1/3 公众号模板消息
            String name = orderInfoList.get(0).getName();
            if (orderInfoList.size()>1 && orderInfoList.get(0).getType().equals(4)){
                if (name.length()>13){
                    name = name.substring(0,13)+"等商品";
                }
            }else {
                if (name.length()>16){
                    name = name.substring(0,16);
                }
            }
            //{{first.DATA}}商品名称：{{keyword1.DATA}}订单号：{{keyword2.DATA}}订单金额：{{keyword3.DATA}}收货时间：{{keyword4.DATA}}{{remark.DATA}}
            HashMap<String,Object> message = new HashMap<>();
            message.put("first","确认收货提醒");
            message.put("keyword1",name);
            message.put("keyword2",storeOrder.getOrderId());
            message.put("keyword3",storeOrder.getPayPrice().toPlainString());
            message.put("keyword4",DateUtil.format(new Date(), Constants.DATE_FORMAT));
            message.put("remark","欢迎下次光临！");
            orderTakeByPublicAccount(message,paySuccessOfEvent.getWechatId(),storeOrder);
        }
        if (paySuccessOfEvent.getIsSms().equals(1)) {
            //  发送短信
            SmsTemplate smsTemplate = smsTemplateService.getDetail(paySuccessOfEvent.getSmsId());
            StoreOrderInfo orderInfo = orderInfoList.get(0);
            if (orderInfoList.size() > 1) {
                generateSmsOrderTake(storeOrder, orderInfo, smsTemplate, true);
            } else {
                generateSmsOrderTake(storeOrder, orderInfo, smsTemplate, false);
            }

        }
        return Boolean.TRUE;
    }

    /**
     * @Description:生成收货小程序订阅消息
     * @author:chenbing
     * @date 2022/12/30 15:55
     */
    private void orderTakePushMessageRoutine(StoreOrder storeOrder, Integer routineId) {

        HashMap<String, String> messageMap = new HashMap<>();
        //订单号{{character_string1.DATA}}收货时间{{time2.DATA}}收件人{{thing3.DATA}}物流单号{{character_string4.DATA}}
        messageMap.put("character_string1", storeOrder.getOrderId());
        messageMap.put("time2", cn.hutool.core.date.DateUtil.format(storeOrder.getClosingTime(), Constants.DATE_FORMAT));
        messageMap.put("thing3", storeOrder.getRealName());
        messageMap.put("character_string4", storeOrder.getMasterWaybillNo());
        UserToken token = userTokenService.getTokenByUserId(storeOrder.getUid(), OrderRedisConstans.SYSTEM_TYPE_ROUTINE);
        templateMessageService.pushMiniTemplateMessage(routineId, messageMap, token.getToken(), "pages/user-order-details/index?orderNo="+storeOrder.getOrderId());

    }

    /**
     * 自动收货公众号消息通知
     * @param message
     * @param wechatId
     * @param storeOrder
     */
    private void  orderTakeByPublicAccount(HashMap<String,Object> message, Integer wechatId, StoreOrder storeOrder){
        String pageUrl = "pages/user-order-details/index?orderNo="+storeOrder.getOrderId();
        UserToken token = userTokenService.getTokenByUserId(storeOrder.getUid(), OrderRedisConstans.SYSTEM_TYPE_ROUTINE);
        if (ObjectUtil.isNotNull(token)){
            templateMessageService.pushTemplatePublicMessage(pageUrl,wechatId, message, token.getToken());
        }
    }

    /**
     * 订单收货短信通知
     *
     * @param order
     * @param storeOrderInfo
     * @param smsTemplate
     */
    private void generateSmsOrderTake(StoreOrder order, StoreOrderInfo storeOrderInfo, SmsTemplate smsTemplate, Boolean isMore) {
        String pageUrl = "pages/user-order-details/index?orderNo="+order.getOrderId();
        if (ObjectUtil.isNotNull(order.getUid())) {
            User user = userService.getById(order.getUid());
            if (ObjectUtil.isNotNull(user.getPhone())) {
                if (isMore) {
                    String name = storeOrderInfo.getName();
                    if (name.length() > 13) {
                        name = storeOrderInfo.getName().substring(0, 13);
                    }
                    name = name + "等商品";
                    smsService.sendOrderConfirmReceipt(name, order.getOrderId(), user.getPhone(), smsTemplate.getTempId(),pageUrl);
                } else {
                    String name = "";
                    if (storeOrderInfo.getName().length() > 16) {
                        name = storeOrderInfo.getName().substring(0, 16);
                    } else {
                        name = storeOrderInfo.getName();
                    }
                    smsService.sendOrderConfirmReceipt(name, order.getOrderId(), user.getPhone(), smsTemplate.getTempId(), pageUrl);
                }

            }
        }
    }

}

